﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using Component.UI;
using Config;
using ExtraFoundation.Components;
using UnityEngine;

namespace Component
{
    public class StationNode : MonoBehaviour
    {
    
        [SerializeField] DrawMeshTools.MeshType meshType;
        float nodeWidth = 1;
        float innerWidth = .7f;
        float target = 2;
        [SerializeField] private int capacity;
        
        private DrawMeshTools mainMeshTools;
        [SerializeField] private DrawMeshTools subMeshTools;
        [SerializeField] private DrawMeshTools borderMeshTools;
        [SerializeField] private DrawMeshTools fadeMeshTools;

        [SerializeField] private float cameraSizeOffset = 0;
        private DrawMeshTools breathMeshTools;
        private DrawMeshTools timerMeshTools;

        private bool playStart;
        public Vector2 EndDirection { get; set; } = Vector2.right;
        private Vector3 originalPos;

        public bool PlayStart => playStart;
        public DrawMeshTools.MeshType Type => meshType;

        private DrawLineTools[] list = new DrawLineTools[TransferTools.MaxColor * 2];
        
        public List<DrawMeshTools.MeshType> ReachableType { get; private set; }
        
        private void Awake()
        {
            mainMeshTools = GetComponent<DrawMeshTools>();
            
            breathMeshTools = CreateMeshTools("breath mesh");
            timerMeshTools = CreateMeshTools("time mesh");
            breathMeshTools.SortLayer = 1;
            timerMeshTools.SortLayer = 1;
        }


        private void Start()
        {
            switch (meshType)
            {
                case DrawMeshTools.MeshType.Round:
                case DrawMeshTools.MeshType.Quad:
                    nodeWidth = 1;
                    innerWidth = .7f;
                    break;
                case DrawMeshTools.MeshType.Triangle:
                    nodeWidth = 1.2f;
                    innerWidth = .8f;
                    break;
            }
            
            originalPos = transform.position;
            mainMeshTools.DrawMesh(meshType, originalPos, nodeWidth, Color.black);
            subMeshTools.DrawMesh(meshType, originalPos, innerWidth, Color.white);

            ReachableType = new List<DrawMeshTools.MeshType> {meshType};
        }

        private void Update()
        {
            PlayBreathAnim(transform.GetChild(0).childCount > GameConfig.StationCapacity);
        }

        private void OnEnable()
        {
            if (Time.time < 3)
            {
                return;
            }
            CameraTools.OrthographicSizeBigger(cameraSizeOffset);
        }

        private DrawMeshTools CreateMeshTools(string meshName)
        {
            var go = new GameObject(meshName);
            go.transform.parent = transform;
            return go.AddComponent<DrawMeshTools>();
        }

        /// <summary>
        /// 返回改点的另一条路线
        /// </summary>
        /// <param name="line">当前的线</param>
        /// <returns>另一条线</returns>
        public DrawLineTools GetLine(DrawLineTools line, bool remove = false)
        {
            if (list[TransferTools.ColorIndex * 2] == line)
            {
                if (remove)
                {
                    list[TransferTools.ColorIndex * 2] = null;
                }
                return list[TransferTools.ColorIndex * 2 + 1];
            }
            if (list[TransferTools.ColorIndex * 2 + 1] == line)
            {
                if (remove)
                {
                    list[TransferTools.ColorIndex * 2 + 1] = null;
                }
                return list[TransferTools.ColorIndex * 2];
            }
            return null;
        }

        /// <summary>
        /// 返回改点的另一条路线
        /// </summary>
        /// <param name="line">当前的线</param>
        /// <returns>另一条线</returns>
        public DrawLineTools GetLine(DrawLineTools line, Color color, bool remove = false)
        {
            if (list[TransferTools.ColorsIndex(color) * 2] == line)
            {
                if (remove)
                {
                    list[TransferTools.ColorsIndex(color) * 2] = null;
                }
                return list[TransferTools.ColorsIndex(color) * 2 + 1];
            }
            if (list[TransferTools.ColorsIndex(color) * 2 + 1] == line)
            {
                if (remove)
                {
                    list[TransferTools.ColorsIndex(color) * 2 + 1] = null;
                }
                return list[TransferTools.ColorsIndex(color) * 2];
            }
            return null;
        }
        
        public DrawLineTools GetLine()
        {
            return list[TransferTools.ColorIndex * 2] != null ? list[TransferTools.ColorIndex * 2] : list[TransferTools.ColorIndex * 2 + 1];
        }
        
        
        public DrawLineTools GetLine(Color color)
        {
            return list[TransferTools.ColorsIndex(color) * 2] != null ? list[TransferTools.ColorsIndex(color) * 2] : list[TransferTools.ColorsIndex(color) * 2 + 1];
        }

        public StationResult[] GetNeighbours(Color currentColor, StationNode current)
        {
            List<StationResult> result = new List<StationResult>();
            for (int i = 0; i < list.Length; i+=2)
            {
                if (list[i] != null && list[i].Color != currentColor)
                {
                    result.Add(new StationResult(list[i].GetNode(current), list[i].Color));
                }
            }
            return result.ToArray();
        }

        public DrawLineTools GetNotEndLine(Color color)
        {
            return list[TransferTools.ColorsIndex(color) * 2].gameObject.layer != LayerMask.NameToLayer("End") ? list[TransferTools.ColorsIndex(color) * 2] : list[TransferTools.ColorsIndex(color) * 2 + 1];
        }

        public void ClearLine()
        {
            list[TransferTools.ColorIndex * 2] = null;
            list[TransferTools.ColorIndex * 2 + 1] = null;
        }
        
        public void SetLine(DrawLineTools line)
        {
            if (list[TransferTools.ColorIndex * 2] == null)
            {
                list[TransferTools.ColorIndex * 2] = line;
            }else if (list[TransferTools.ColorIndex * 2 + 1] == null)
            {
                list[TransferTools.ColorIndex * 2 + 1] = line;
            }
        }

        public void ReplaceLine(DrawLineTools original, DrawLineTools newLine)
        {
            if (original == list[TransferTools.ColorIndex * 2])
            {
                list[TransferTools.ColorIndex * 2] = newLine;
            }

            if (original == list[TransferTools.ColorIndex * 2 + 1])
            {
                list[TransferTools.ColorIndex * 2 + 1] = newLine;
            }
        }
        

        public bool SingleDrawable()
        {
            return (list[TransferTools.ColorIndex * 2] == null || list[TransferTools.ColorIndex * 2 + 1] == null) && !doubleDrawable();
        }

        public bool doubleDrawable()
        {
            return list[TransferTools.ColorIndex * 2] == null && list[TransferTools.ColorIndex * 2 + 1] == null;
        }
        
        /**
         * 节点动画
         */
        public void NodeHover()
        {
            if (!playStart)
            {
                task = new Task(borderMeshTools.OnClickMeshAnim(meshType, originalPos, nodeWidth, target, TransferTools.Color, (nodeWidth + target)/2));
                task.Finished += manual =>
                {
                    borderMeshTools.ClearMesh();
                };
                        
                fadeTask = new Task(fadeMeshTools.OnClickMeshAnim(
                    meshType, 
                    originalPos, 
                    nodeWidth * 2, 
                    target * 2, 
                    new Color(TransferTools.Color.r, TransferTools.Color.g, TransferTools.Color.b, .2f)));
                        
                fadeTask.Finished += manual =>
                {
                    fadeMeshTools.ClearMesh();
                };
                playStart = true;
            }
        }

        public void NodeHoverOver()
        {
            if(!playStart)
                return;
            task.Stop();
            fadeTask.Stop();
            playStart = false;
        }

        private Task breathTask;

        private void PlayBreathAnim(bool play)
        {
            if (play)
            {
                if (breathTask == null || (breathTask != null && !breathTask.Running))
                {
                    breathTask = new Task(DrawBreathMeshAnim(DrawMeshTools.MeshType.Round, 
                        transform.position, nodeWidth * 8, new Color(Color.black.r, Color.black.g, Color.black.b, 1f)));
                    StartCoroutine(TimeClicker());
                    breathTask.Finished += manual =>
                    {
                        breathMeshTools.ClearMesh();
                        // StopCoroutine(TimeClicker());
                    };
                    
                }
            }
            else
            {
                if (breathTask != null && breathTask.Running)
                {
                    breathTask.Stop();
                }
            }

            if (play && timer < GameConfig.Countdown)
            {
                timer += Time.deltaTime;
            }else if (!play && timer > 0)
            {
                timer -= Time.deltaTime;
            }

            if (timer > GameConfig.Countdown)
            {
                GameManager.Instance.GameOverFocus(transform.position);
            }
        }
        
        private IEnumerator DrawBreathMeshAnim(DrawMeshTools.MeshType type, Vector2 center, float maxLength, Color color)
        {
            float currentLength = 0;
            float currentVelocity = 0;
            float targetLength = maxLength;
            while (true)
            {
                currentLength = Mathf.SmoothDamp(currentLength, targetLength,ref currentVelocity,.8f);
                color.a = Mathf.Clamp(.49f - currentLength / targetLength * .5f, 0, 1);
                
                if (currentLength > maxLength - .1f)
                {
                    currentLength = 0;
                }
                
                breathMeshTools.DrawMesh(type, center, currentLength, color);
         
                yield return new WaitForSeconds(Time.deltaTime);
            }
        }

        private float timer = 0;
        private IEnumerator TimeClicker()
        {
            while (true)
            {
                var currentAngle = Mathf.Clamp(timer / GameConfig.Countdown * 360, 0, 360);
                timerMeshTools.DrawRing(nodeWidth * 1.2f, 0, 180, transform.position, new Color(0,0,0,.5f),currentAngle);
                yield return new WaitForSeconds(Time.deltaTime);
            }
        }
    
        private Task task;
        private Task fadeTask;
        
        public struct StationResult
        {
            public StationNode Station;
            public Color Color;

            public StationResult(StationNode station, Color color)
            {
                Station = station;
                Color = color;
            }
        }
        
    }
}